home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / doc / rexx.doc < prev    next >
Text File  |  1994-02-13  |  26KB  |  780 lines

  1.  
  2.                DICE AREXX SUPPORT
  3.  
  4.     XXX handle sending a command w/ multiple arguments
  5.     XXX handle custom returns of messages
  6.  
  7.     DICE maintains several routines to automatically handle most of the
  8.     grunt work involved in writing a program with AREXX support, you as
  9.     a programmer need only setup part of the event loop and the command
  10.     dispatch.  By calling DICE's ARexx support routines you automatically
  11.     cause DICE to bring in startup and exit code to maintain it.
  12.  
  13.     The first thing you need to do is declare char *RexxHostName;  You have
  14.     two choices (example).
  15.  
  16.     char *RexxHostName = "DME";
  17.     char *RexxHostName = NULL;
  18.  
  19.     The first case is the most common -- by declaring RexxHostName with a
  20.     string DICE will automatically setup its ARexx subsystem and
  21.     automatically create an application ARexx port, finding an appropriate
  22.     slot number 01 through 99 (the actual port will be named DME.nn where nn
  23.     is 01 through 99).    Note that DICE sets up its ARexx subsystem BEFORE
  24.     YOUR MAIN() IS CALLED, so the assignment to RexxHostName must be part
  25.     of the declaration.
  26.  
  27.     The second case, declaring RexxHostName to be NULL, causes DICE to
  28.     setup it's ARexx subsystem but *NOT* create any ARexx ports.  Your
  29.     main() must then create a Global ARexx port using:
  30.  
  31.     r = CreateGlobalDiceRexxPort(NULL, char *globalName);
  32.  
  33.     Passing NULL as the message port causes DICE to initialize it's
  34.     internal RexxPort structure as a global ARexx message port.
  35.  
  36.     If you do not do either of the above two steps beware that DICE's
  37.     internal RexxPort will be invalid and unusable.
  38.  
  39.     Regardless of how you initialize RexxHostName, DICE will automatically
  40.     open rexxsyslib.library for you.  DICE can handle an arbitrary number
  41.     of nesting levels and multiple ARexx ports simultaniously.    Finally,
  42.     DICE fully resource tracks all ARexx operations done through this
  43.     interface, including messages in progress, allowing ^C BREAK to be
  44.     operational at all times!    That is, DICE WILL AUTOMATICALLY CLEANUP
  45.     THE MESS THAT IS LEFT IF SOMEONE BREAK's THE PROGRAM 5 NESTING LEVELS
  46.     DEEP.
  47.  
  48.     DICE's automatic AREXX support is brought in if you reference any DICE
  49.     ARexx command such as ProcessRexxCommands() (which you need to have
  50.     for your part of the interface anyway).
  51.  
  52.     You can, at any time, create and destroy DICE supported ARexx ports.
  53.     This is done via the CreateDiceRexxPort(), CreateGlobalDiceRexxPort()
  54.     calls, and DeleteDiceRexxPort) calls.  CreateDiceRexxPort() will modify
  55.     your supplied port name with a slot number, finding a free slot number
  56.     and returning it (-1 on failure).  CreateGlobalDiceRexxPort() will
  57.     not modify your supplied port name.  If you pass NULL as the port name
  58.     for either routine DICE will create a private ARexx port instead of a
  59.     public one.
  60.  
  61.  
  62.     ------------------------------ EXAMPLE 1 -----------------------------
  63.  
  64.     This example shows how to setup a global port to redirect commands to
  65.     the proper instance of the application.
  66.  
  67.     1> dcc gtest.c -o gtest
  68.     1> run gtest
  69.     1> run gtest a
  70.     1> run gtest b
  71.     1> rx gtest.rexx
  72.  
  73.     The first instance of the program, gtest without arguments, sets up a
  74.     global port called "GTEST".  Each of the other instances of the program
  75.     setup application ports "GTEST.xx".  The rexx script sends a command
  76.     to the global port and the first gtest process then scans through all
  77.     possible application ports sending the command to them until one
  78.     returns success.
  79.  
  80.     If you run the above you will note that the 'a' and 'b' commands in
  81.     the rexx script succeeded but the 'c' command failed.  If you now run
  82.     a gtest to handle c:
  83.  
  84.     1> run gtest c
  85.  
  86.     And run the rexx script again, all will succeed.
  87.  
  88.  
  89.     #include <lib/rexx.h>
  90.     #include <clib/exec_protos.h>
  91.     #include <string.h>
  92.     #include <stdlib.h>
  93.     #include <stdio.h>
  94.     #include <dos/dos.h>
  95.  
  96.     char Buf[256];
  97.  
  98.     /*
  99.      *    This program shows off using a global port for the program verses
  100.      *    an application port.  You run the program as follows:
  101.      *
  102.      */
  103.  
  104.     char *RexxHostName = NULL;    /* no automatic start */
  105.  
  106.     char *MyCommand;        /* left NULL for global port */
  107.  
  108.     main(ac, av)
  109.     char *av[];
  110.     {
  111.  
  112.     /*
  113.      *  DICE automatically opens rexxsyslib.library for us as long
  114.      *  as we reference the base variable (via extern) and not
  115.      *  declare it.  lib/rexx.h does this for us.
  116.      *
  117.      *  However, unlike other autoinits, if DICE is unable to open
  118.      *  the library it does not abort the program, hence the following.
  119.      */
  120.  
  121.     if (RexxSysBase == NULL) {
  122.         puts("Unable to open rexxsyslib.library !");
  123.         exit(20);
  124.     }
  125.  
  126.     /*
  127.      *  We left RexxHostName = NULL because our program will create
  128.      *  either a global port or an application port and we don't know
  129.      *  which one yet.
  130.      *
  131.      *  Our call to Create[Global]DiceRexxPort(NULL, ...) will cause
  132.      *  DICE to initialize our RexxHostName properly.
  133.      */
  134.  
  135.     if (ac == 1) {    /* no arguments, create global port */
  136.         short r = CreateGlobalDiceRexxPort(NULL, "GTEST");
  137.         if (r < 0) {
  138.         puts("Unable to create global port GTEST, already exists?");
  139.         exit(20);
  140.         }
  141.         printf("Created global port for redirect to proper app\n");
  142.     } else {    /* arguments, create local app port */
  143.         short r = CreateDiceRexxPort(NULL, "GTEST");
  144.         if (r < 0) {
  145.         puts("Unable to create application port GTEST!");
  146.         exit(20);
  147.         }
  148.         printf("Created application port GTEST.%02d for '%s'\n", r, av[1]);
  149.         MyCommand = av[1];
  150.     }
  151.     {
  152.         char *ptr;
  153.         int slotNo;
  154.  
  155.         slotNo = GetDiceRexxPortSlot(NULL, &ptr);
  156.         printf("slot: %d '%s'\n", slotNo, ptr);
  157.     }
  158.  
  159.     /*
  160.      *  Our main loop executes received commands
  161.      */
  162.  
  163.     for (;;) {
  164.         long mask = Wait(SIGBREAKF_CTRL_C | (1 << RexxSigBit));
  165.  
  166.         if (mask & SIGBREAKF_CTRL_C) {
  167.         printf("Terminating %s\n", (ac == 1) ? "global" : av[1]);
  168.         exit(1);
  169.         }
  170.         if (mask & (1 << RexxSigBit))
  171.         ProcessRexxCommands(NULL);
  172.     }
  173.     }
  174.  
  175.     /*
  176.      *    Our command handler depends on MyCommand... do we attempt to
  177.      *    execute the command or do we attempt to pass it on to application
  178.      *    ports ?
  179.      */
  180.  
  181.     long
  182.     DoRexxCommand(msg, port, arg0, pres)
  183.     void *msg;            /*    RexxMsg structure if we need it     */
  184.     struct MsgPort *port;   /*    MsgPort structure if we need it     */
  185.     char *arg0;     /*    arg0                    */
  186.     char **pres;    /*    where to put our result if rc==0    */
  187.     {
  188.     int rc;
  189.  
  190.     if (MyCommand == NULL) {
  191.         short i;
  192.         char buf[32];
  193.  
  194.         printf("Global Redirect command: %s\n", arg0);
  195.  
  196.         for (i = 1; i < 100; ++i) {
  197.         sprintf(buf, "%s.%02d", RexxHostName, i);
  198.         if ((rc = PlaceRexxCommandDirect(NULL, buf, arg0, pres, NULL)) == 0)
  199.             break;
  200.         }
  201.         if (i == 100) {
  202.         printf("Global: Command failed\n");
  203.         rc = 5;
  204.         }
  205.     } else {
  206.         printf("MatchCheck %s vs %s\n", arg0, MyCommand);
  207.         if (stricmp(arg0, MyCommand) == 0) {
  208.         *pres = "success!";
  209.         rc = 0;
  210.         } else {
  211.         *pres = "failure";
  212.         rc = 5;
  213.         }
  214.     }
  215.     return(rc);
  216.     }
  217.  
  218.  
  219.  
  220.  
  221.     --------- gtest.rexx --------
  222.     /* gtest */
  223.  
  224.     OPTIONS RESULTS
  225.  
  226.     address GTEST
  227.  
  228.     RESULT = 'no result'
  229.     a
  230.     say RC ',' RESULT
  231.  
  232.     RESULT = 'no result'
  233.     b
  234.     say RC ',' RESULT
  235.  
  236.     RESULT = 'no result'
  237.     c
  238.     say RC ',' RESULT
  239.  
  240.  
  241.     ------------------------------ EXAMPLE 2 -----------------------------
  242.  
  243.     This example shows off DICE's capability to arbitrarily nest ARexx
  244.     commands.
  245.  
  246.     To test, run the program in one CLI and the rexx script in another.
  247.     Try running the rexx script without typing ^E from the test program,
  248.     then try running the rexx script after typing ^E from the test program
  249.     (to enable the second ARexx port).
  250.  
  251.     Finally, just for fun, try ^C (BREAKing) your test program while it's
  252.     in the middle of processing ARexx commands.
  253.  
  254.     1> dcc test.c -o test
  255.     1> test
  256.     ...
  257.  
  258.     2> rx xx.rexx
  259.     etc...
  260.  
  261.  
  262.  
  263.     #include <lib/rexx.h>
  264.     #include <clib/exec_protos.h>
  265.     #include <string.h>
  266.     #include <stdlib.h>
  267.     #include <stdio.h>
  268.     #include <dos/dos.h>
  269.  
  270.     char Buf[256];
  271.  
  272.     /*
  273.      *    This program shows off using two ports.  The first is created
  274.      *    automatically by DICE using RexxHostName as the template.  The
  275.      *    second we create manually.  You can dynamically create as many
  276.      *    ports as you wish.  In this example, hitting ^E creates the second
  277.      *    port and hitting ^F deletes it.
  278.      *
  279.      *    Note that DICE automatically creates an application port.. that is,
  280.      *    in a slot number <portname>.00 through <portname>.99  If you want
  281.      *    to create a global public port, i.e. just <portname>, specify NULL
  282.      *    for RexxHostName then use CreateGlobalDiceRexxPort().  DICE will
  283.      *    automatically stuff a NULL RexxHostName with your global port name
  284.      *    For future PlaceRexxCommand() calls.
  285.      */
  286.  
  287.     struct MsgPort TmpPort;
  288.     short TmpPortValid;
  289.  
  290.     /*
  291.      *    You MUST have an INITIALIZED declaration to specify the master
  292.      *    port name.  DICE references this variable *before* _main or
  293.      *    even __main is run!!!!    Therefore, only static initialization
  294.      *    as that shown below will work.
  295.      */
  296.  
  297.     char *RexxHostName = "FUBAR";
  298.  
  299.     /*
  300.      *    This little variable limits the nesting levels for our tests
  301.      */
  302.  
  303.     long Cnts;
  304.  
  305.     main(ac, av)
  306.     char *av[];
  307.     {
  308.     /*
  309.      *  DICE automatically opens rexxsyslib.library if we
  310.      *  reference it's base variable or DICE's ARexx support
  311.      *  routines.
  312.      *
  313.      *  However, DICE does not automatically abort if it cannot
  314.      *  open the library so we must check for success here.
  315.      *  (DICE normally aborts the program automatically if any
  316.      *  autoinit library fails to open, rexxsyslib is an exception)
  317.      */
  318.  
  319.     if (RexxSysBase == NULL) {
  320.         puts("Unable to open rexxsyslib.library !");
  321.         exit(20);
  322.     }
  323.  
  324.     /*
  325.      *  The program demonstrates both waiting for an incomming
  326.      *  ARexx command (on any number of ports) and dispatching REXX
  327.      *  commands.
  328.      *
  329.      *  To handle incomming ARexx commands you wait for your ARexx
  330.      *  signal to come in (1 << RexxSigBit) then call
  331.      *  ProcessRexxCommands(NULL) which forces DICE to scan all
  332.      *  known ARexx ports belonging to this program.  Alternately
  333.      *  you can specify a pointer to a message port to process the
  334.      *  commands associated with a single port, but beware that
  335.      *  you must be sure to handle all pending input before going
  336.      *  back to your Wait() or you may lock yourself out!
  337.      *
  338.      *  To dispatch a REXX command you call PlaceRexxCommand() with
  339.      *  appropriate arguments.  If you pass a non-NULL char ** to
  340.      *  hold the result then DICE will put the result string in
  341.      *  the returned pointer.  You must free() this string when
  342.      *  you are done with it.  The string might be returned as NULL
  343.      *  if no result string is returned from the ARexx command, so
  344.      *  check for that condition too!
  345.      *
  346.      *  Note that DICE will automatically clean up in-progress REXX
  347.      *  messages if you ^C !  Do NOT attempt to reply these messages
  348.      *  yourself!
  349.      */
  350.  
  351.     puts("Type ^D followed by a rexx command");
  352.     puts("or run a rex script using host FUBAR with commands 'hello' or 'test'");
  353.     puts("or type ^C to exit");
  354.  
  355.     for (;;) {
  356.         long mask = Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F | (1 << RexxSigBit));
  357.  
  358.         if (mask & SIGBREAKF_CTRL_E) {
  359.         if (TmpPortValid == 0) {
  360.             puts("CREATE FU2");
  361.             CreateDiceRexxPort(&TmpPort, "FU2");
  362.             TmpPortValid = 1;
  363.         }
  364.         }
  365.  
  366.         /*
  367.          *    WARNING!  You may only call DeleteDiceRexxPort() from
  368.          *    the top level.    You CANNOT call DeleteDiceRexxPort()
  369.          *    while nested within an ARexx command as you might delete
  370.          *    the port out from under yourself.  In a real application
  371.          *    this means that you need to handle your CLOSE command
  372.          *    (to close a project within an application) as a special
  373.          *    case since you cannot call DeleteDiceRexxPort() for that
  374.          *    project while in the middle of ARexx processing!
  375.          */
  376.  
  377.         if (mask & SIGBREAKF_CTRL_F) {
  378.         if (TmpPortValid == 1) {
  379.             puts("DELETE FU2");
  380.             DeleteDiceRexxPort(&TmpPort);
  381.             TmpPortValid = 0;
  382.         }
  383.         }
  384.  
  385.         if (mask & SIGBREAKF_CTRL_D) {
  386.         char *res;
  387.         long rc;
  388.         long ec;
  389.  
  390.         printf("rexx command? ");
  391.         fflush(stdout);
  392.         gets(Buf);
  393.  
  394.         rc = PlaceRexxCommand(NULL, Buf, &res, &ec);
  395.         printf("result: rc=%d res=%s\n", rc, ec, res ? res : "<null>");
  396.         if (res)
  397.             free(res);
  398.         }
  399.         if (mask & SIGBREAKF_CTRL_C)
  400.         exit(1);
  401.         if (mask & (1 << RexxSigBit))
  402.         ProcessRexxCommands(NULL);
  403.     }
  404.     return(0);
  405.     }
  406.  
  407.     /*
  408.      *    We must supply a DoRexxCommand() routine, it returns the
  409.      *    return code.  A pointer to the RexxMsg structure is passed
  410.      *    though in most cases you will not need to reference it.  DICE
  411.      *    will AUTOMATICALLY reply the message based on how you set *pres
  412.      *    and what error code you return.
  413.      *
  414.      *    It is perfectly legal to call PlaceRexxCommand() from this
  415.      *    routine.  However, you must be careful NEVER to call
  416.      *    DeleteDiceRexxPort() from this routine!
  417.      *
  418.      *    A pointer to hte MsgPort structure that the message came in
  419.      *    on is passed allowing you to determine which project the
  420.      *    message applies to.
  421.      */
  422.  
  423.     long
  424.     DoRexxCommand(msg, port, arg0, pres)
  425.     void *msg;            /*    RexxMsg structure if we need it     */
  426.     struct MsgPort *port;   /*    MsgPort structure if we need it     */
  427.     char *arg0;     /*    arg0                    */
  428.     char **pres;    /*    where to put our result if rc==0    */
  429.     {
  430.     printf("PORT %-10s received %s\n", port->mp_Node.ln_Name, arg0);
  431.     if (stricmp(arg0, "hello") == 0) {
  432.         *pres = "goodbye!";
  433.         return(0);
  434.     } else if (stricmp(arg0, "test") == 0) {
  435.         *pres = "test on you too!";
  436.         return(0);
  437.     } else if (strnicmp(arg0, "recurse", 7) == 0) {
  438.         long rc = 1;
  439.  
  440.         ++Cnts;
  441.         if (Cnts < 10) {
  442.         rc = PlaceRexxCommand(NULL, arg0 + 8, pres, NULL);
  443.         printf("tried to run %s, got rc=%d res=%s\n", arg0 + 8, rc, *pres ? *pres : "<null>");
  444.         }
  445.         --Cnts;
  446.         return(rc);
  447.     }
  448.  
  449.     /*
  450.      *  unrecognized command
  451.      */
  452.  
  453.     return(5);
  454.     }
  455.  
  456.  
  457.  
  458.     --------- xx.rexx --------
  459.     /* xx */
  460.  
  461.     OPTIONS RESULTS
  462.  
  463.     address FUBAR.01
  464.  
  465.     RESULT = 'no result'
  466.     hello
  467.     say RC ',' RESULT
  468.  
  469.     RESULT = 'no result'
  470.     test
  471.     say RC ',' RESULT
  472.  
  473.     RESULT = 'no result'
  474.     xxx
  475.     say RC ',' RESULT
  476.  
  477.     recurse yy.rexx
  478.  
  479.     --------- yy.rexx --------
  480.     /* yy */
  481.  
  482.     OPTIONS RESULTS
  483.  
  484.     address FU2.01
  485.  
  486.     RESULT = 'no result'
  487.     hello
  488.     say RC ',' RESULT
  489.  
  490.     RESULT = 'no result'
  491.     test
  492.     say RC ',' RESULT
  493.  
  494.     RESULT = 'no result'
  495.     xxx
  496.     say RC ',' RESULT
  497.  
  498.     recurse xx.rexx
  499.  
  500.             SPECIFYING YOUR PROGRAM'S REXX HOST NAME
  501.  
  502.     DICE initializes RexxPort *before* your main() is called, and uses the
  503.     contents of the RexxHostName variable at that time. Therefore, when
  504.     implementing an ARexx interface you normally set the variable using static
  505.     initialization, that is:
  506.  
  507.     char *RexxHostName = "name_of_my_port";
  508.  
  509.     Setting up the variable in main(), or even in _main() will be too late.
  510.     If you declare RexxHostName = NULL then DICE will not initialize an
  511.     ARexx port (you can do so manually from main() in that case by calling
  512.     either CreateDiceRexxPort() or CreateGlobalDiceRexxPort() with a NULL
  513.     port).
  514.  
  515.     DICE will also use the contents of this variable for your default ARexx
  516.     script extension.
  517.  
  518.                    PARSING
  519.  
  520.     When adding REXX support into your program note that you must parse the
  521.     argument string yourself.  The first argument (arg0) is broken out of
  522.     the RexxMsg for you and in simple instances, as in our test program
  523.     above, you do not even have to reference the RexxMsg passed to you.
  524.  
  525.     As far as return values go, you must return a result code and may also
  526.     optionally setup a result string.  DICE will duplicate the contents of
  527.     the string but since you return from your procedure before this occurs
  528.     you cannot use a local variable for your result buffer.  The result
  529.     string is a pointer to a pointer and preinitialized to NULL, so if you
  530.     do not return a result you need not bother with it at all.
  531.  
  532.     Result strings are only valid when an error code of 0 is returned.
  533.  
  534.     A pointer to the MsgPort that the ARexx command was received on is also
  535.     passed to allow you to determine which project it applies to.
  536.  
  537.                   MULTIPLE REXX PORTS
  538.  
  539.     DICE fully supports multiple ARexx ports and can handle arbitrary
  540.     nesting of ARexx messages on any given port or amoung several or all
  541.     the ports.    DICE will properly backout of multiply nested ARexx
  542.     commands over multiple ports if the program gets aborted with ^C,
  543.     exit(), abort(), whatever...
  544.  
  545.     Refer to the CreateDiceRexxPort() and DeleteDiceRexxPort() command
  546.     descriptions below.
  547.  
  548.  
  549.     CreateGlobalDiceRexxPort()                CreateGlobalDiceRexxPort()
  550.  
  551.     void CreateDiceRexxPort(msgPort, name)
  552.     struct MsgPort *msgPort;
  553.     char *name;
  554.  
  555.     This call integrates any number of ARexx ports beyond the master port
  556.     into DICE's ARexx system.  This call may be made from any point in your
  557.     program.  After this call returns the message port will accept
  558.     incomming ARexx messages.
  559.  
  560.     Note that for simple programs you can simply use the master port
  561.     (RexxPort) that DICE sets up for you automatically and need not bother
  562.     with creating additional ports.  This call is more of use in more
  563.     complex programs which handle multiple projects simultaniously.
  564.  
  565.     msgPort    - A blank msgPort structure (that is, totally zero'd out).
  566.           DICE will fill the structure with appropriate values.
  567.           DICE uses the same signal bit as it allocated for the
  568.           master port (RexxPort).  Finally, DICE makes the message
  569.           port public through the AddPort() call.
  570.  
  571.           If you had declared RexxHostName as NULL causing DICE to
  572.           not initialize an internal default RexxPort, you can pass
  573.           NULL here to initialize DICE's internal default RexxPort,
  574.           thereby allowing PlaceRexxCommand() calls that specify a
  575.           NULL port (i.e. to use DICE's internal default RexxPort).
  576.           You are not required to use DICE's internal message port,
  577.           it is simply convenient.
  578.  
  579.     name    - A pointer to the name of the message port.  DICE uses this
  580.           name verbatim.  An error (-1) is returned if the port
  581.           already exists.  If you had passed NULL for the MsgPort
  582.           structure DICE will initialize RexxHostName to name.
  583.  
  584.     RETURN VALUE - 0 is returned on success, -1 on error
  585.  
  586.  
  587.     CreateDiceRexxPort()                CreateDiceRexxPort()
  588.  
  589.     short r = CreateDiceRexxPort(msgPort, name)
  590.     struct MsgPort *msgPort;
  591.     char *name;
  592.  
  593.     This call integrates any number of ARexx ports beyond the master port
  594.     into DICE's ARexx system.  This call may be made from any point in your
  595.     program.  After this call returns the message port will accept
  596.     incomming ARexx messages.
  597.  
  598.     Note that for simple programs you can simply use the master port
  599.     (RexxPort) that DICE sets up for you automatically and need not bother
  600.     with creating additional ports.  This call is more of use in more
  601.     complex programs which handle multiple projects simultaniously.
  602.  
  603.     msgPort    - A blank msgPort structure (that is, totally zero'd out).
  604.           DICE will fill the structure with appropriate values.
  605.           DICE uses the same signal bit as it allocated for the
  606.           master port (RexxPort).  Finally, DICE makes the message
  607.           port public through the AddPort() call.
  608.  
  609.           If you had declared RexxHostName as NULL causing DICE to
  610.           not initialize an internal default RexxPort, you can pass
  611.           NULL here to initialize DICE's internal default RexxPort,
  612.           thereby allowing PlaceRexxCommand() calls that specify a
  613.           NULL port (i.e. to use DICE's internal default RexxPort).
  614.           You are not required to use DICE's internal message port,
  615.           it is simply convenient.
  616.  
  617.     name    - A pointer to the name of the message port. DICE adds a .NN
  618.           extension to this name, finding a free slot number when
  619.           creating a public message port.  If you pass NULL for this
  620.           field, DICE will create a private message port suitable for
  621.           handling ARexx call-backs.  An error (-1) is returned if
  622.           no slots are available (all 99 are in use).  If you had
  623.           passed NULL for the MsgPort structure then DICED will
  624.           initialize RexxHostName to the extended name.
  625.  
  626.     RETURN VALUE - the slot number is returned, -1 if an error occured.
  627.  
  628.  
  629.  
  630.     DeleteDiceRexxPort()                DeleteDiceRexxPort()
  631.  
  632.     void DeleteDiceRexxPort(msgPort)
  633.     struct MsgPort *msgPort;
  634.  
  635.     This call deletes a previously created DICE ARexx port.  You may NOT
  636.     delete any ARexx port while within DoRexxCommand().  This call may only
  637.     be made from the top level of your program or you run the risk of
  638.     deleted an ARexx port out from under yourself.
  639.  
  640.     You may NOT delete the master ARexx port, only those you specifically
  641.     create.
  642.  
  643.     This call automatically clears out any as yet unread messages on the
  644.     port, removes the port from the public message list with RemPort(), and
  645.     zero's the structure.
  646.  
  647.  
  648.  
  649.     PlaceRexxCommand()                    PlaceRexxCommand()
  650.  
  651.     long PlaceRexxCommand(port, str, &res, &ec)
  652.     struct MsgPort *port;
  653.     char *str;
  654.     char *res;
  655.     long ec;
  656.  
  657.     This command sends an ARexx command off to ARexx.  The command is
  658.     normally a script file to run.  You must specify the ARexx port that is
  659.     to act as the default host port for the command or NULL to use DICE's
  660.     default port. The default extension for the script is always the
  661.     RexxHostName variable.  Note that if you specify NULL for the port to
  662.     use DICE's default, then you must have previously setup DICE's default
  663.     port.  This occurs automatically if RexxHostName was declared non-NULL,
  664.     or manually if you had called Create[Global]DiceRexxPort(NULL, "name").
  665.  
  666.     You supply the command in 'str' which is made Arg0.  Currently there is
  667.     no support for additional arguments XXX.  DICE will run the command
  668.     synchronously and return the result code.
  669.  
  670.     The result string pointer will be set to either NULL or a malloc()'d
  671.     string.  If not NULL you are responsible for free()ing the result
  672.     string when you are through with it!!  If you wish to ignore any
  673.     result you may pass NULL for this argument.
  674.  
  675.     The ec longword will be set to an internal ARexx error code... if the
  676.     returned result code is non-zero and ec == 1 then ARexx was unable to
  677.     find the specified ARexx command.  You may pass NULL for this argument
  678.     if you do not care about the error code.
  679.  
  680.     It is possible that your program will receive ARexx commands while it
  681.     is waiting for the command you have sent to be returned.  DICE will
  682.     automatically call DoRexxCommand() from within the PlaceRexxCommand()
  683.     routine when this case occurs.
  684.  
  685.     ARexx will set the error-code (ec), which is different from the
  686.     result-code.  ec is set to 1 if the script could not be found. ARexx
  687.     normally returns a severity code of 5 for this case.  If the return
  688.     code is 0 then ec will be 0.
  689.  
  690.  
  691.     PlaceRexxCommandDirect()                 PlaceRexxCommandDirect()
  692.  
  693.     long PlaceRexxCommandDirect(port, remoteName, str, &res, &ec);
  694.     ...
  695.     char *remoteName;
  696.  
  697.     This command is similar to PlaceRexxCommand() but sends the command to
  698.     a specification application instead of to AREXX.
  699.  
  700.  
  701.     ProcessRexxCommands()                ProcessRexxCommands()
  702.  
  703.     void ProcessRexxCommands(msgPort/NULL)
  704.     struct MsgPort *msgPort;
  705.  
  706.     In order to process incomming ARexx commands you must call the
  707.     ProcessRexxCommands() routine when you receive the signal
  708.     RexxSigBit (signal mask is (1 << RexxSigBit)).
  709.  
  710.     Passing NULL to this routine will cause DICE to scan ALL KNOWN ARexx
  711.     ports belonging to this program... that is, the master port and all
  712.     created ports.  DICE will call DoRexxCommand() for each ARexx command
  713.     received as well as weed out returned messages from any ARexx commands
  714.     we have sent that are still in progress.
  715.  
  716.     If you wish, you can pass a specific message port to have DICE only
  717.     process ARexx commands received on a specific port, but beware that
  718.     your Wait() on the signal bit has cleared the signal and you should be
  719.     sure to process all message ports before calling Wait() again, else
  720.     risk leaving unprocessed ARexx messages queued in and then blocking in
  721.     Wait() !
  722.  
  723.  
  724.  
  725.     DoRexxCommand()                    DoRexxCommand()
  726.  
  727.     long
  728.     DoRexxCommand(msg, port, arg0, pres)
  729.     void *msg;
  730.     struct MsgPort *port;
  731.     char *arg0;
  732.     char **pres;
  733.  
  734.     DoRexxCommand() is a routine that YOU supply to process incomming ARexx
  735.     requests.  DICE will call your routine for any requests it processes
  736.     with ProcessRexxCommands() as well as for any requests that come in
  737.     during processing of a PlaceRexxCommand().    DICE presets *pres to
  738.     NULL.
  739.  
  740.     To return an error simply return a non-zero error code.
  741.  
  742.     To return a string set *pres to point to the string and return(0); DICE
  743.     will make a copy of the string to return to ARexx but you should note
  744.     that since your procedure must return before DICE can do this, you
  745.     cannot assign *pres to any local stack variables.
  746.  
  747.  
  748.     GetDiceRexxPortSlot()                GetDiceRexxPortSlot()
  749.  
  750.     int
  751.     GetDiceRexxPortSlot(port, nameptr)
  752.     MsgPort *port;
  753.     char **nameptr;
  754.  
  755.     GetDiceRexxPortSlot() returns the ln_Name field of the specified port
  756.     (i.e. the fully qualified port name) and extracts and returns the slot
  757.     number.  -1 is returned if the port name does not terminate with ".xx"
  758.     where xx is a number.  If a char ** pointer is passed as nameptr it will
  759.     be initialized to point to the ln_Name field of the port.
  760.  
  761.     This call is normally used with port = NULL to obtain information about
  762.     DICE's internally setup Rexx port.
  763.  
  764.     port:    message port structure to extract ln_Name and slot field from.
  765.         You can pass NULL to extract the full name and slot number
  766.         selected by DICE when automatic startup is used (i.e. your
  767.         declaration of RexxHostName is assigned a non-NULL pointer).
  768.  
  769.     nameptr:    a pointer to a char * (that is, a char **) or NULL.  If not
  770.         NULL the pointer will be assigned the ln_Name field of the
  771.         port.  Normally used when port is passed as NULL to obtain
  772.         the fully qualified rexx port name DICE has constructed for
  773.         you in an automatic startup.
  774.  
  775.     RETURN:
  776.  
  777.     slotno:    the slot number extracted from the port name or -1 if the
  778.         port name is not in the proper format.
  779.  
  780.